package botobjects;

import interfaces.BotObject;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import tools.StringTools;
import tools.UtopiaTime;
import database.DBConnectionFactory;
import exceptions.UtoDateException;

public class NewsItem implements BotObject, Comparable<NewsItem> {
   /**
    * Returns a list of news. Can be specified to only fetch items in a specific time interval, or to get the latest added items
    * 
    * @param firstDate
    *           News from before this date are ignored
    * @param lastDate
    *           News from after this date are ignored
    * @param lastAdded
    *           Decides whether the last added items should be returned, or a regular list of items
    * @return a List of NewsItems
    */
   public static List<NewsItem> getNews(final String firstDate, final String lastDate, final boolean lastAdded) {
	  List<NewsItem> out = new LinkedList<NewsItem>();
	  if (firstDate == null || lastDate == null)
		 return out;
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 if (lastAdded) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM " + "news ORDER BY realtime DESC,id DESC LIMIT 4");
		 } else if ("".equals(firstDate)) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM news ORDER BY realtime,id");
		 } else if ("".equals(lastDate)) {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM " + "news WHERE realtime >= ? ORDER BY realtime,id");
			ps.setTimestamp(1, new Timestamp(new UtopiaTime(firstDate.replace(" of", "th,")).getTime()));
		 } else {
			ps = DBConnectionFactory.getConnectionHandler().getConnection()
				  .prepareStatement("SELECT * FROM " + "news WHERE realtime >= ? AND realtime <= ? ORDER BY realtime,id");
			ps.setTimestamp(1, new Timestamp(new UtopiaTime(firstDate.replace(" of", "th,")).getTime()));
			ps.setTimestamp(2, new Timestamp(new UtopiaTime(lastDate.replace(" of", "th,")).getTime()));
		 }
		 rs = ps.executeQuery();

		 while (rs.next()) {
			out.add(new NewsItem(rs.getString("utodate"), rs.getString("newsitem"), rs.getInt("amount")));
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } catch (final UtoDateException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   public String date = "";
   public String news = "";

   public int amount = 0;

   public NewsItem(final String date, final String news, final int amount) {
	  this.date = date;
	  this.news = news;
	  this.amount = amount;
   }

   /**
    * Compares two NewsItems based on the uto date, since it's only used to order them
    */
   @Override
   public int compareTo(final NewsItem compare) {
	  try {
		 final Long time = new UtopiaTime(date.replace(" of", "th,")).getTime();
		 final Long compareTime = new UtopiaTime(compare.date.replace(" of", "th,")).getTime();
		 if (time < compareTime)
			return -1;
		 else if (time > compareTime)
			return 1;
	  } catch (final UtoDateException e) {
		 Logger.getLogger("Error").error("", e);
	  }
	  return 0;
   }

   /**
    * Compares two NewsItems based on the uto date, since it's only used to order them
    */
   @Override
   public boolean equals(final Object o) {
	  if (o == null)
		 return false;
	  if (o instanceof NewsItem)
		 return date.equals(((NewsItem) o).date) && news.equals(((NewsItem) o).news);
	  return false;
   }

   @Override
   public List<String> getIRCOutput(final int outputType, final String... args) {
	  // not used
	  return new LinkedList<String>();
   }

   @Override
   public Map<String, Object> getRPCOutput(final int... includes) {
	  Map<String, Object> out = new HashMap<String, Object>();
	  if (StringTools.isNullOrEmpty(date) || StringTools.isNullOrEmpty(news))
		 return out;
	  out.put("Date", date);
	  out.put("News", news);
	  out.put("Amount", amount);
	  return out;
   }

   @Override
   public int hashCode() {
	  assert false : "hashCode not designed";
	  return 42;
   }

   @Override
   public boolean saveToDB() {
	  // do nothing
	  return false;
   }

   public static synchronized boolean saveBatch(final List<NewsItem> news) {
	  boolean out = false;
	  PreparedStatement ps = null;
	  try {
		 ps = DBConnectionFactory.getConnectionHandler().getConnection()
			   .prepareStatement("DELETE FROM news WHERE utodate = ? AND newsitem = ?" + " AND amount = ?");
		 for (NewsItem ni : news) {
			ps.setString(1, ni.date);
			ps.setString(2, ni.news);
			ps.setInt(3, ni.amount);
			ps.addBatch();
		 }

		 ps.executeBatch();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = DBConnectionFactory.getConnectionHandler().getConnection()
			   .prepareStatement("INSERT INTO news VALUES(default,?,?,?,?)");
		 for (NewsItem ni : news) {
			ps.setString(1, ni.date);
			ps.setString(2, ni.news);
			ps.setInt(3, ni.amount);
			ps.setTimestamp(4, new Timestamp(new UtopiaTime(ni.date.replace(" of", "th,")).getTime()));
			ps.addBatch();
		 }
		 ps.executeBatch();
		 out = true;
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } catch (final UtoDateException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }
}
